import re
from typing import List, Optional
from pathlib import Path


class InputValidator:
    """输入验证器"""
    
    # 危险的 Markdown 模式
    DANGEROUS_PATTERNS = [
        r'<script.*?>',  # JavaScript
        r'<iframe.*?>',  # 内嵌框架
        r'<object.*?>',  # 对象标签
        r'<embed.*?>',   # 嵌入内容
        r'javascript:',  # JavaScript URL
        r'data:.*base64', # Base64 数据 URL (可能包含恶意内容)
    ]
    
    # 支持的图片格式
    SUPPORTED_IMAGE_FORMATS = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'}
    
    # 支持的视频格式
    SUPPORTED_VIDEO_FORMATS = {'.mp4', '.avi', '.mov', '.wmv', '.mkv'}
    
    @classmethod
    def validate_markdown_content(cls, content: str) -> tuple[bool, Optional[str]]:
        """验证 Markdown 内容是否安全"""
        if not content or not content.strip():
            return False, "Markdown content cannot be empty"
        
        # 检查内容长度
        if len(content) > 10 * 1024 * 1024:  # 10MB
            return False, "Markdown content too large (max 10MB)"
        
        # 检查危险模式  
        content_lower = content.lower()
        for pattern in cls.DANGEROUS_PATTERNS:
            if re.search(pattern, content_lower, re.IGNORECASE):
                return False, f"Potentially dangerous content detected: {pattern}"
        
        return True, None
    
    @classmethod
    def validate_theme(cls, theme: str, supported_themes: List[str]) -> tuple[bool, Optional[str]]:
        """验证主题名称"""
        if not theme:
            return False, "Theme cannot be empty"
        
        if theme not in supported_themes:
            return False, f"Unsupported theme: {theme}. Supported themes: {', '.join(supported_themes)}"
        
        return True, None
    
    @classmethod
    def validate_filename(cls, filename: str) -> tuple[bool, Optional[str]]:
        """验证文件名"""
        if not filename:
            return False, "Filename cannot be empty"
        
        # 检查文件名长度
        if len(filename) > 255:
            return False, "Filename too long (max 255 characters)"
        
        # 检查危险字符
        dangerous_chars = ['<', '>', ':', '"', '|', '?', '*', '\\', '/']
        for char in dangerous_chars:
            if char in filename:
                return False, f"Filename contains dangerous character: {char}"
        
        # 检查文件扩展名
        if not filename.endswith('.pptx'):
            return False, "Output filename must have .pptx extension"
        
        return True, None
    
    @classmethod
    def validate_image_width_ratio(cls, ratio: float) -> tuple[bool, Optional[str]]:
        """验证图片宽度比例"""
        if not isinstance(ratio, (int, float)):
            return False, "Image width ratio must be a number"
        
        if ratio <= 0 or ratio > 1:
            return False, "Image width ratio must be between 0 and 1"
        
        return True, None
    
    @classmethod
    def validate_file_path(cls, file_path: str) -> tuple[bool, Optional[str]]:
        """验证文件路径"""
        if not file_path:
            return False, "File path cannot be empty"
        
        path = Path(file_path)
        
        # 检查文件是否存在
        if not path.exists():
            return False, f"File does not exist: {file_path}"
        
        # 检查是否为文件
        if not path.is_file():
            return False, f"Path is not a file: {file_path}"
        
        # 检查文件扩展名
        if path.suffix.lower() != '.md':
            return False, f"File must be a Markdown file (.md): {file_path}"
        
        # 检查文件大小
        try:
            file_size = path.stat().st_size
            if file_size > 10 * 1024 * 1024:  # 10MB
                return False, f"File too large (max 10MB): {file_size} bytes"
        except OSError as e:
            return False, f"Cannot access file: {e}"
        
        return True, None
    
    @classmethod
    def sanitize_filename(cls, filename: str) -> str:
        """清理文件名，移除危险字符"""
        # 移除或替换危险字符
        dangerous_chars = ['<', '>', ':', '"', '|', '?', '*', '\\', '/']
        sanitized = filename
        
        for char in dangerous_chars:
            sanitized = sanitized.replace(char, '_')
        
        # 移除前后空格
        sanitized = sanitized.strip()
        
        # 确保不为空
        if not sanitized:
            sanitized = "output.pptx"
        
        # 确保有正确的扩展名
        if not sanitized.endswith('.pptx'):
            sanitized = sanitized.rsplit('.', 1)[0] + '.pptx'
        
        return sanitized